package tabela;


import interfaceusuario.CriaPainelDeFundoComBackground;
import interfaceusuario.CriadorImageIcon;
import interfaceusuario.CriadorTextLabel;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.LinkedList;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;

public class PainelTabela extends JPanel implements MouseListener
{
	protected int quantasColunasTemATabela;
	protected LinkedList<LinhaTabela> linhasDaTabela;
	private LinkedList<String> cabecalhosDaTabela;
	protected GridBagConstraints grid;
	protected JLabel botaoAdicionarLinha;
	protected JLabel botaoDeletarLinhasSelecionadas;
	protected JLabel botaoConfirmarDeletarLinhasSelecionadas; /*esse botao ficarah escondido
	 														e soh aparece quando o painel entra
	 														no modo deletar linhas*/
	
	protected boolean tabelaNoModoDeletarLinhas;
	protected int quantasLinhasForamDeletadasNaTabela;
	/*o inteiro acima aumenta caso linhas sejam deletadas da tabela e diminui
	 * caso linhas entrem na tabela apos terem sido deletadas alguma vez*/
	
	public PainelTabela(LinkedList<String> cabecalhos)
	{
		//definir cor do painel
		this.setBackground(new Color(60, 106, 44));
		
		this.quantasColunasTemATabela = cabecalhos.size();
		
		this.cabecalhosDaTabela = new LinkedList<String>();
		for(int i = 0; i < cabecalhos.size(); i++)
		{
			String umCabecalho = cabecalhos.get(i);
			if(umCabecalho.length() >= 20)
			{
				umCabecalho = umCabecalho.substring(0, 19) + "...";
			}
			
			this.cabecalhosDaTabela.add(umCabecalho);
			
		}
		
		GridBagLayout layout = new GridBagLayout();
		this.setLayout(layout);
		
		this.grid = new GridBagConstraints();
		
		this.linhasDaTabela = new LinkedList<LinhaTabela>();
		
		this.tabelaNoModoDeletarLinhas = false;
		this.quantasLinhasForamDeletadasNaTabela = 0;
		
		this.criarCabecalhoDaTabela();
		this.criarLinhaDaTabela();
		
		ThreadAtualizaPainelTabela thread = new ThreadAtualizaPainelTabela(this);
		thread.start();
		
		//a thread acima ficarah atualizando a tabela o tempo todo
	}
	
	public PainelTabela(LinkedList<String> cabecalhos, LinkedList<String> valores)
	{
		this.setBackground(new Color(60, 106, 44));
		
		this.quantasColunasTemATabela = cabecalhos.size();
		
		this.cabecalhosDaTabela = new LinkedList<String>();
		for(int i = 0; i < cabecalhos.size(); i++)
		{
			String umCabecalho = cabecalhos.get(i);
			if(umCabecalho.length() >= 20)
			{
				umCabecalho = umCabecalho.substring(0, 19) + "...";
			}
			
			this.cabecalhosDaTabela.add(umCabecalho);
			
		}
		
		GridBagLayout layout = new GridBagLayout();
		this.setLayout(layout);
		
		this.grid = new GridBagConstraints();
		
		this.linhasDaTabela = new LinkedList<LinhaTabela>();
		
		this.tabelaNoModoDeletarLinhas = false;
		
		this.criarCabecalhoDaTabela();
		this.criarLinhasDaTabelaComValores(valores);
		
		ThreadAtualizaPainelTabela thread = new ThreadAtualizaPainelTabela(this);
		thread.start();
		
		//a thread acima ficarah atualizando a tabela o tempo todo
	}
	
	private void criarCabecalhoDaTabela()
	{
		this.grid.gridx = 0;
		this.grid.gridy = 0;
		grid.fill = GridBagConstraints.HORIZONTAL;
		grid.anchor = GridBagConstraints.SOUTH;
		
		for(int i = 0; i < this.quantasColunasTemATabela; i++)
		{
			//para cada coluna, um cabecalho
			String umCabecalho = this.cabecalhosDaTabela.get(i);
			
			JLabel labelDoCabecalho;
			
			labelDoCabecalho = CriadorTextLabel.criarTextlabel(umCabecalho, 17);
			
			
			JPanel painelCabecalho = new JPanel();
			painelCabecalho.add(labelDoCabecalho);
			painelCabecalho.setBorder(new LineBorder(Color.black,5));
			painelCabecalho.setBackground(Color.blue);
			
			this.add(painelCabecalho,grid);
			this.grid.gridx = this.grid.gridx + 1;
		}
		
		grid.anchor = GridBagConstraints.CENTER;
		
		criarBotoesParaAdicionarRemoverLinhaDeTabela();
	}
	
	/*essa funcao abaixo eh chamada logo apos criacao do cabecalho da tabela*/
	private void criarBotoesParaAdicionarRemoverLinhaDeTabela()
	{
		this.grid.gridx = this.quantasColunasTemATabela;  
		this.grid.gridy = 0;
		//ou seja, o botao adicionar sera colocado em uma outra coluna, logo a direita da tabela
		
		ImageIcon imagemBotaoAdicionar = 
				CriadorImageIcon.criarImageIcon("imagens/botaoadd.png", "botao +");
		this.botaoAdicionarLinha = new JLabel(imagemBotaoAdicionar);
		
		this.botaoAdicionarLinha.addMouseListener(this);
		this.add(botaoAdicionarLinha,grid);
		
		this.grid.gridy = 1;
		JPanel painelRemoverEBotaoEscondidoOk = CriaPainelDeFundoComBackground.getInstance().criarPainelDeFundoPadraoDoSistema();
		
		ImageIcon imagemBotaoDeletar = 
				CriadorImageIcon.criarImageIcon("imagens/botaodelete.png", "botao delete");
		this.botaoDeletarLinhasSelecionadas = new JLabel(imagemBotaoDeletar);
		
		ImageIcon imagemBotaoConfirmarDeletar = 
				CriadorImageIcon.criarImageIcon("imagens/botaook.png", "botao ok");
		this.botaoConfirmarDeletarLinhasSelecionadas = new JLabel(imagemBotaoConfirmarDeletar);
		
		painelRemoverEBotaoEscondidoOk.add(this.botaoDeletarLinhasSelecionadas);
		painelRemoverEBotaoEscondidoOk.add(this.botaoConfirmarDeletarLinhasSelecionadas);
		this.botaoConfirmarDeletarLinhasSelecionadas.setVisible(false);
		
		
		this.botaoDeletarLinhasSelecionadas.addMouseListener(this);
		this.botaoConfirmarDeletarLinhasSelecionadas.addMouseListener(this);
		
		this.add(painelRemoverEBotaoEscondidoOk,grid);
		
		this.grid.gridy = 0; //fiz isso somente para quando for adicionar uma linha na tabela,
							//adicionar desde a linha na grid apos o cabecalho
		
	}
	
	public void criarLinhaDaTabela()
	{
		LinhaTabela linha = new LinhaTabela(this.quantasColunasTemATabela);
		this.linhasDaTabela.add(linha);
		
		//agora vamos inserir essa linha na tabela
		this.grid.gridx = 0;
		this.grid.gridy = this.grid.gridy + 1;
		
		LinkedList<JTextField> textFieldsDaLinha = linha.pegarTextFieldsDaLinha();
		for(int i = 0; i < textFieldsDaLinha.size(); i++)
		{
			JTextField umTextField = textFieldsDaLinha.get(i);
			grid.fill = GridBagConstraints.HORIZONTAL; //faz as celulas ficarem grudadas
			if(this.linhasDaTabela.size() == 1)
			{
				/*a primeira linha da tabela eh especial: Precisamos orienta-la para
				 *ficar encostando no fundo da celula da grid onde ela esta. Senao
				 *a primeira linha da tabela ficarah separada das outras linhas*/
				grid.anchor = GridBagConstraints.SOUTH;
				
			}
			this.add(umTextField, this.grid);
			
			grid.anchor = GridBagConstraints.CENTER;
			grid.fill = GridBagConstraints.CENTER; //vamos fazer esse fill voltar ao centro soh por precaucao
			
			this.grid.gridx = this.grid.gridx + 1;
		}
		
		/*alem de adicionar uma nova linha, devemos ja informar para essa nova linha se a tabela esta 
		  no modo de deletar linhas ou nao. Por default as linha sao criadas sem estar no modo de deletar
		 */
		linha.setTabelaNoModoDeletarLinhas(this.tabelaNoModoDeletarLinhas);
	}

	/*cria somente uma linha da tabela com os valores passados*/
	public void criarUmaLinhaDaTabelaPreenchida(LinkedList<String> valores)
	{
		LinhaTabela linha = new LinhaTabela(this.quantasColunasTemATabela);
		this.linhasDaTabela.add(linha);
		
		//agora vamos inserir essa linha na tabela
		this.grid.gridx = 0;
		this.grid.gridy = this.grid.gridy + 1;
		
		LinkedList<JTextField> textFieldsDaLinha = linha.pegarTextFieldsDaLinha();
		for(int i = 0; i < textFieldsDaLinha.size(); i++)
		{
			JTextField umTextField = textFieldsDaLinha.get(i);
			String umValor = valores.get(i);
			umTextField.setText(umValor);
			
			grid.fill = GridBagConstraints.HORIZONTAL; //faz as celulas ficarem grudadas
			if(this.linhasDaTabela.size() == 1)
			{
				/*a primeira linha da tabela eh especial: Precisamos orienta-la para
				 *ficar encostando no fundo da celula da grid onde ela esta. Senao
				 *a primeira linha da tabela ficarah separada das outras linhas*/
				grid.anchor = GridBagConstraints.SOUTH;
				
			}
			this.add(umTextField, this.grid);
			
			grid.anchor = GridBagConstraints.CENTER;
			grid.fill = GridBagConstraints.CENTER; //vamos fazer esse fill voltar ao centro soh por precaucao
			
			this.grid.gridx = this.grid.gridx + 1;
		}
		
		/*alem de adicionar uma nova linha, devemos ja informar para essa nova linha se a tabela esta 
		  no modo de deletar linhas ou nao. Por default as linha sao criadas sem estar no modo de deletar
		 */
		linha.setTabelaNoModoDeletarLinhas(this.tabelaNoModoDeletarLinhas);
	}
	
	/*cria varias linhas da tabela preenchidas com os valores passados*/
	public void criarLinhasDaTabelaComValores(LinkedList<String> valores)
	{	
		boolean todosOsValoresForamUsados = false;
		
		while(todosOsValoresForamUsados == false)
		{	
			LinhaTabela linha = new LinhaTabela(this.quantasColunasTemATabela);
			this.linhasDaTabela.add(linha);
			
			//agora vamos inserir essa linha na tabela
			this.grid.gridx = 0;
			this.grid.gridy = this.grid.gridy + 1;
			
			LinkedList<JTextField> textFieldsDaLinha = linha.pegarTextFieldsDaLinha();
			for(int j = 0; j < textFieldsDaLinha.size(); j++)
			{
				JTextField umTextField = textFieldsDaLinha.get(j);
				
				if(valores.size() > 0)
				{
					String umValor = valores.removeFirst();
					umTextField.setText(umValor);
					
					grid.fill = GridBagConstraints.HORIZONTAL; //faz as celulas ficarem grudadas
					if(this.linhasDaTabela.size() == 1)
					{
						/*a primeira linha da tabela eh especial: Precisamos orienta-la para
						 *ficar encostando no fundo da celula da grid onde ela esta. Senao
						 *a primeira linha da tabela ficarah separada das outras linhas*/
						grid.anchor = GridBagConstraints.SOUTH;
						
					}
					this.add(umTextField, this.grid);
					
					grid.anchor = GridBagConstraints.CENTER;
					grid.fill = GridBagConstraints.CENTER; //vamos fazer esse fill voltar ao centro soh por precaucao
					
					this.grid.gridx = this.grid.gridx + 1;
				}
				else
				{
					todosOsValoresForamUsados = true;
				}
			}
			
			if(valores.size() <= 0)
			{
				todosOsValoresForamUsados = true;
			}
			
			/*alem de adicionar uma nova linha, devemos ja informar para essa nova linha se a tabela esta 
			  no modo de deletar linhas ou nao. Por default as linha sao criadas sem estar no modo de deletar
			 */
			linha.setTabelaNoModoDeletarLinhas(this.tabelaNoModoDeletarLinhas);
			
		}
	}
	
	
	public LinkedList<LinhaTabela> pegarLinhasDaTabela()
	{
		return this.linhasDaTabela;
	}
	
	@Override
	public void mouseClicked(MouseEvent arg0) 
	{
		if(arg0.getSource() == this.botaoDeletarLinhasSelecionadas)
		{
			if(this.tabelaNoModoDeletarLinhas == false)
			{
				//entrou no modo de deletar linhas
				this.tabelaNoModoDeletarLinhas = true;
				
				ImageIcon iconeBotaoCancelar = CriadorImageIcon.criarImageIcon("imagens/botaoreturn.png", "botao return");
				
				this.botaoDeletarLinhasSelecionadas.setIcon(iconeBotaoCancelar);
				this.botaoConfirmarDeletarLinhasSelecionadas.setVisible(true);
				for(int i = 0; i < this.linhasDaTabela.size(); i++)
				{
					LinhaTabela umaLinha = linhasDaTabela.get(i);
					umaLinha.setTabelaNoModoDeletarLinhas(true);
				}
			}
			else
			{
				//saiu do modo de deletar linhas
				this.sairDoModoDeDeletarLinhas();
			}
		}
		else if(arg0.getSource() == this.botaoAdicionarLinha)
		{
			this.criarLinhaDaTabela();
			//uma linha da tabela foi criada? Entao vamos mudar o contador de linhas deletadas da tabela caso seja necessario
			if(this.quantasLinhasForamDeletadasNaTabela > 0)
			{
				this.quantasLinhasForamDeletadasNaTabela = this.quantasLinhasForamDeletadasNaTabela - 1;
			}
			
		}
		else if(arg0.getSource() == this.botaoConfirmarDeletarLinhasSelecionadas)
		{
			deletarLinhasSelecionadas();
			this.sairDoModoDeDeletarLinhas();
		}
		
	}

	@Override
	public void mouseEntered(MouseEvent arg0) 
	{
		Cursor cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); 
	    setCursor(cursor);
		
	}

	@Override
	public void mouseExited(MouseEvent arg0) 
	{
		Cursor cursor = Cursor.getDefaultCursor(); 
	    setCursor(cursor);
		
	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	
	protected void sairDoModoDeDeletarLinhas()
	{
		this.tabelaNoModoDeletarLinhas = false;
		ImageIcon imagemDeletar =
				CriadorImageIcon.criarImageIcon("imagens/botaodelete.png", "botao deletar");
		this.botaoDeletarLinhasSelecionadas.setIcon(imagemDeletar);
		
		
		this.botaoConfirmarDeletarLinhasSelecionadas.setVisible(false);
		for(int i = 0; i < this.linhasDaTabela.size(); i++)
		{
			LinhaTabela umaLinha = linhasDaTabela.get(i);
			umaLinha.setTabelaNoModoDeletarLinhas(false);
		}
	}
	
	protected void deletarLinhasSelecionadas()
	{
		LinkedList<LinhaTabela> novasLinhasDaTabela = new LinkedList<LinhaTabela>();
		for(int i = 0; i < this.linhasDaTabela.size(); i++)
		{
			LinhaTabela umaLinha = this.linhasDaTabela.get(i);
			if(umaLinha.getLinhaEstahSelecionada() == false)
			{
				novasLinhasDaTabela.add(umaLinha);
			}
			else
			{
				//alguma linha sera deletada!Vamos mudar o contador de linhas deletadas
				this.quantasLinhasForamDeletadasNaTabela = this.quantasLinhasForamDeletadasNaTabela + 1;
			}
		}
		
		this.recriarTodoOPainelComNovasLinhas(novasLinhasDaTabela);
	}
	
	
	protected void recriarTodoOPainelComNovasLinhas(LinkedList<LinhaTabela> novasLinhas)
	{
		//primeiro destruiremos a tabela que ja existia
		this.destruirTodaATabela();
		
		for(int i = 0; i < novasLinhas.size(); i++)
		{
			this.linhasDaTabela.add(novasLinhas.get(i));
		}
		
		//agora vamos pintar no painel essas linhas novamente
		for(int j = 0; j < this.linhasDaTabela.size(); j++)
		{
			LinhaTabela umaLinha = this.linhasDaTabela.get(j);
			this.grid.gridx = 0;
			this.grid.gridy = this.grid.gridy + 1;
			
			LinkedList<JTextField> textFieldsDaLinha = umaLinha.pegarTextFieldsDaLinha();
			for(int i = 0; i < textFieldsDaLinha.size(); i++)
			{
				JTextField umTextField = textFieldsDaLinha.get(i);
				grid.fill = GridBagConstraints.HORIZONTAL; //faz as celulas ficarem grudadas
				
				if(j == 0)
				{
					/*a primeira linha da tabela eh especial: Precisamos orienta-la para
					 *ficar encostando no fundo da celula da grid onde ela esta. Senao
					 *a primeira linha da tabela ficarah separada das outras linhas*/
					grid.anchor = GridBagConstraints.SOUTH;
				}
				this.add(umTextField, this.grid);
				
				grid.anchor = GridBagConstraints.CENTER;
				
				this.grid.gridx = this.grid.gridx + 1;
			}
			
			/*por precaucao, vamos fazer a linha ficar nao no modo de deletar linhas
			 */
			umaLinha.setTabelaNoModoDeletarLinhas(false);
		}
		
		if(this.linhasDaTabela.size() == 0)
		{
			/*nao ha linhas da tabela restantes? Vamos adicionar pelo menos uma linha.
			 * Afinal, nao ha tabela sem linhas!*/
			this.criarLinhaDaTabela();
		}
	}

	public void destruirTodaATabela()
	{
		//primeiro vamos remover tudo que estiver dentro do painel
		this.removeAll();
				
		//agora vamos criar o cabecalho novamente
		this.grid.gridx = 0;
		this.grid.gridy = 0;
		this.criarCabecalhoDaTabela();
				
		//agora vamos tirar todas as linhas da tabela(se a tabela foi criada pela primeira vez, ela tem pelo menos 1 linha)
		this.linhasDaTabela.clear();
	}
	
	public boolean existeAlgumaLinhaDaTabelaNaoPreenchida()
	{
		for(int i = 0; i < linhasDaTabela.size(); i++)
		{
			LinhaTabela umaLinha = this.linhasDaTabela.get(i);
			LinkedList<JTextField> textFieldsDaLinha = umaLinha.pegarTextFieldsDaLinha();
			
			for(int j = 0; j < textFieldsDaLinha.size(); j++)
			{
				if(textFieldsDaLinha.get(j).getText().length() == 0)
				{
					return true;
				}
			}
		}
		return false;
	}
	
	/*se a tabela nao tem linha nenhuma ou todas as linhas estao vazias, ela esta vazia*/
	public boolean tabelaEstahVazia()
	{
		if(linhasDaTabela.size() == 0)
		{
			return true;
		}
		else
		{
			for(int i = 0; i < this.linhasDaTabela.size(); i++)
			{
				LinhaTabela umaLinha = linhasDaTabela.get(i);
				
				LinkedList<JTextField> textFieldsDaLinha = umaLinha.pegarTextFieldsDaLinha();
				
				for(int j = 0; j < textFieldsDaLinha.size(); j++)
				{
					if(textFieldsDaLinha.get(j).getText().length() != 0)
					{
						return false;
					}
				}
			}
			
			//percorri todas as linhas da tabela e nenhuma estava preenchida
			return true;
		}
	}
	
	public JLabel getBotaoAdicionarLinha()
	{
		return this.botaoAdicionarLinha;
	}

	public int getQuantasLinhasForamDeletadasNaTabela() 
	{
		return quantasLinhasForamDeletadasNaTabela;
	}
}
